package com.ryzx.log.collector;

import com.ryzx.common.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

/*
处理请求controller层日志输出
 */
@Slf4j
@Aspect
public class ControllerLogHandler extends AbstractLogHandler {
    private static final String REQUEST_MESSAGE_FORMAT = "URL=[{0}],method=[{1}],handle class=[{2}],handle method=[{3}],Param=[{4}],Response=[{5}],cost time=[{6}ms-({7})]";
    private static final String REQUEST_MESSAGE_ERROR_FORMAT = "URL=[{0}],method=[{1}],handle class=[{2}],handle method=[{3}],Param=[{4}],stackTrac=[\n{5}]";
    private static final String REQUEST_MESSAGE_MULIT_FORMAT = "URL=[{0}],request method=[{1}],handle class=[{2}],handle method=[{3}]";

    @Pointcut("@within(org.springframework.web.bind.annotation.RestController) && execution(public * *(..) )")
    public void controllerPoincut() {

    }
    @Around("controllerPoincut()")
    public Object doControllerAround(ProceedingJoinPoint point) throws Throwable {
        String traceId = RequestLogContext.getTraceId();
        if(traceId==null)
            traceId=super.processRequestTraceId();
        Long startTime = System.currentTimeMillis();
        MethodLogInfo methodLogInfo = super.buildMethodInfo(point);
        Object controllerResp = point.proceed();
        Long endTime = System.currentTimeMillis();
        long cost = endTime - startTime;
        String path = methodLogInfo.getPath();
        String className = methodLogInfo.getClassName();
        String method = methodLogInfo.getMethod();
        String methodName = methodLogInfo.getMethodName();
        if (!methodLogInfo.isMultiFileMark()) {
            String paramsStr = methodLogInfo.getParamsStr();
            String timeFlag = getTimeCostFlag(cost);
            String controllerRespStr = JsonUtil.obj2String(controllerResp);
            log.info("{\"traceId\":\"{}\",\"url\":\"{}\",\"method\":\"{}\",\"handleClass\":\"{}\",\"handleMethod\":\"{}\",\"param\":\"{}\",\"response\":{},\"costTime\":\"{}\",\"timeLevel\":\"{}\",\"stackTrace\":\"{}\"}",
                    traceId,path,method,className,methodName,paramsStr,controllerRespStr,cost,timeFlag,"");
        } else {
            Object[] paramsArray = new Object[]{
                    path, method, className, methodName
            };
            log.info("{\"traceId\":\"{}\",\"url\":\"{}\",\"method\":\"{}\",\"handleClass\":\"{}\",\"handleMethod\":\"{}\",\"param\":\"{}\",\"response\":{},\"costTime\":\"{}\",\"timeLevel\":\"{}\",\"stackTrace\":\"{}\"}",
                    traceId,path,method,className,methodName,"","",-1,"","");
        }
        return controllerResp;
    }
    @AfterThrowing(pointcut = "controllerPoincut()", throwing = "e")
    public void handle(JoinPoint point, Exception e) {
        String traceId = RequestLogContext.getTraceId();
        if(traceId==null)
            traceId=super.processRequestTraceId();
        MethodLogInfo methodLogInfo = super.buildMethodInfo(point);
        String path = methodLogInfo.getPath();
        String className = methodLogInfo.getClassName();
        String method = methodLogInfo.getMethod();
        String methodName = methodLogInfo.getMethodName();
        String paramsStr = methodLogInfo.getParamsStr();
        String stackTrace=e.toString();
        stackTrace=stackTrace.replace('\"', '\'');
        log.error("{\"traceId\":\"{}\",\"url\":\"{}\",\"method\":\"{}\",\"handleClass\":\"{}\",\"handleMethod\":\"{}\",\"param\":\"{}\",\"response\":{},\"costTime\":\"{}\",\"timeLevel\":\"{}\",\"stackTrace\":\"{}\"}",
                traceId,path,method,className,methodName,paramsStr,"\"\"",-1,"",stackTrace);
    }
}